﻿from collections import defaultdict
import re
from backEnd.settings import DATABASES
from django.db.models.query import QuerySet
from django.http.response import FileResponse
from django.utils.module_loading import import_string
import jwt
from django.conf import settings
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt
from rest_framework import status
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.viewsets import ModelViewSet

from . import models
from .customPermissions import adminPermission, teacherPermission, studentPermission, workerPermission
from .customPermissions.adminPermission import isAdmin
from .customPermissions.studentPermission import isStudent
from .customPermissions.teacherPermission import isTeacher
from .customPermissions.workerPermission import isWorker
from .customPermissions.admin_workerPermission import isAdmin_Worker

from .models import equipment, user, epRunning, repair, scrap, uploadFile
from .serializers import epSerializer, in_userSerializer, out_userSerializer, epRunningSerializer, repairSerializer, \
    scrapSerializer, scrapSerializer1, repairSerializer1, uploadFileSerializer
from rest_framework.generics import GenericAPIView
from rest_framework.mixins import CreateModelMixin, ListModelMixin, RetrieveModelMixin, UpdateModelMixin, \
    DestroyModelMixin
from .utils.jwt_token import create_token
from rest_framework.permissions import IsAdminUser
from rest_framework.decorators import action
from management.utils.jwt_auth import jwtHeaderAuthentication


@method_decorator(csrf_exempt, name='dispatch')
class loginView(ModelViewSet):
    # 对登录视图不认证不鉴权是正确的，恢复安全模式时，除这里外，其他视图类的不认证和不鉴权都关闭。
    authentication_classes = []  # 不认证
    permission_classes = []  # 不鉴权
    serializer_class = out_userSerializer

    queryset = None

    @action(methods=['post'], detail=True, url_path='login', name='login')
    def login(self, request):
        """
        登录接口
        :param request:
        :return:
        """


        data = request.data
        # print(data)
        # import pymysql
        # conn = pymysql.connect(host="121.36.40.195",user="root",password="mypassword",db="management")
        # cursor =conn.cursor()
        # sqlselect = "select * from management_user where id = '{0}' and password = '{1}';".format(data['id'],data['password'])
        # # print(sqlselect)
        # cursor.execute(sqlselect)
        # queryset = cursor.fetchall()
        # print(queryset)
         

        queryset = user.objects.filter(**request.data)  # 防sql注入

        if queryset:
            id = request.data["id"]
            token = create_token({'id': id})
            #type = queryset[0][2]                # 允许sql注入
            type =queryset[0].type             # 防sql注入
            return Response({"type": type, "token": token})

        else:
            return Response({"detail": "用户名或密码错误"})

    @action(methods=['patch'], detail=True, url_path='changePassword', name='changePassword')
    def change(self, request):
        """
        任意用户修改密码
        :param request:
        :return:
        """
        self.authentication_classes = [jwtHeaderAuthentication]

        token = request.META.get('HTTP_AUTHORIZATION')
        salt = settings.SECRET_KEY
        payload = jwt.decode(token, salt, True)
        models.user.objects.filter(id=payload['id']).update(password=request.data['password'])
        query = user.objects.get(id=payload['id'])
        return Response(out_userSerializer(instance=query).data, status=status.HTTP_200_OK)


@method_decorator(csrf_exempt, name='dispatch')
class usrGenView(GenericAPIView, ListModelMixin, CreateModelMixin, RetrieveModelMixin, DestroyModelMixin,
                 UpdateModelMixin):
    #authentication_classes = []
    permission_classes = [isAdmin]  # 只允许管理员处理
    # permission_classes=[]

    # authentication_classes = []  # 不认证
    # permission_classes = []  # 不鉴权

    serializer_class = out_userSerializer
    queryset = user.objects.all()

    def get(self, request):
        """
        管理员查看（指定类型）用户
        :param request:
        :return: 不返回密码
        """
        params = dict(request.query_params)
        if bool(params):
            # 如果有传参
            if 'type' in params.keys():
                # 查询指定类型
                queryset = user.objects.filter(type=params['type'][0])
                serializer = out_userSerializer(instance=queryset, many=True)
                return Response(serializer.data, status=status.HTTP_200_OK)
            elif 'id' in params.keys():
                # 查询指定id
                queryset = user.objects.get(id=params['id'][0])
                serializer = out_userSerializer(instance=queryset)
                return Response(serializer.data, status=status.HTTP_200_OK)
            else:
                # 参数非id或者type，则返回所有数据
                return self.list(request)
        else:
            # 无参，返回所有数据
            return self.list(request)

    def post(self, request):
        """
        管理员批量增加用户
        :param request:
        :return:
        """
        datas = request.data
        for data in datas:
            serializer = in_userSerializer(data=data)
            serializer.is_valid(raise_exception=True)
            serializer.save()

        for i in range(len((datas))):
            if 'password' in datas[i].keys():
                datas[i].pop('password')  # 不返回密码
        return Response(datas, status=status.HTTP_201_CREATED)

    def patch(self, request, pk):

        """
        管理员逐一修改信息：密码或账户类型
        :param request:
        :param pk:
        :return:
        """
        instance = self.get_object()
        serializer = in_userSerializer(instance, data=request.data, partial=True)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        query = user.objects.get(id=pk)
        return Response(out_userSerializer(instance=query).data, status=status.HTTP_200_OK)

    def delete(self, request, pk):
        """
        管理员逐一删除学工用户
        :param request:
        :param pk:
        :return:
        """
        if   request.META.get('HTTP_PERMISSION') == "I'm admin!":
            return self.destroy(request)
        else:
            return Response({"msg":"非法操作！"}, status=status.HTTP_403_FORBIDDEN)
        # self.destroy(request)  # 模拟csrf漏洞


@method_decorator(csrf_exempt, name='dispatch')
class eqGenView(GenericAPIView, ListModelMixin, RetrieveModelMixin, CreateModelMixin, UpdateModelMixin,
                DestroyModelMixin):
    permission_classes = [isAdmin]  # 仅限管理员可以访问

    #authentication_classes = []  # 不认证
    #permission_classes = []  # 不鉴权


    serializer_class = epSerializer
    queryset = equipment.objects.all()
    lookup_field = 'pk'

    def get(self, request):
        """
        管理员查询所有设备信息
        :param request:
        :return:
        """
        return self.list(request)

    def post(self, request):
        """
        管理员批量增加设备信息
        :param request:
        :return:
        """
        datas = request.data
        for data in datas:
            data["exist"] = int(data["unit"])  # 同步现存数据
            serializer = self.get_serializer(data=data)
            serializer.is_valid(raise_exception=True)
            serializer.save()
        return Response(datas, status=status.HTTP_201_CREATED)

    def patch(self, request, pk):
        """
        局部更新
        :param request:
        :param pk:
        :return:
        """
        # 此处存在一个问题，就是修改的数据如果是unit，那么exist也需要根据客观情况，决定是否修改！

        return self.partial_update(request)

    def delete(self, request, pk):
        """
        删除指定设备id
        :param request:
        :param pk:
        :return:
        """
        return self.destroy(request)


@method_decorator(csrf_exempt, name='dispatch')
class epRunGenView(GenericAPIView, ListModelMixin, UpdateModelMixin, DestroyModelMixin):
    serializer_class = epRunningSerializer
    queryset = epRunning.objects.all()

    #authentication_classes = []  # 不认证
    permission_classes = []  # 不鉴权

    def get(self, request):
        """
        查询满足筛选条件的数据
        :param request:
        :return:
        """

        params = dict(request.query_params)
        if bool(params):
            """如果传递的有参数"""
            for key, val in params.items():
                params[key] = val[0]

            """支持多条件组合查询"""
            if 'deviceName' not in params.keys():  # 若设备名不在
                if 'enableDate' not in params.keys():
                    queryset = epRunning.objects.filter(**params)
                    serializer = epRunningSerializer(instance=queryset, many=True)
                    return Response(serializer.data, status=status.HTTP_200_OK)
                else:
                    enableDate = params['enableDate']
                    params.pop('enableDate')
                    queryset = epRunning.objects.filter(enableDate__contains=enableDate).filter(**params)
                    serializer = epRunningSerializer(instance=queryset, many=True)
                    return Response(serializer.data, status=status.HTTP_200_OK)
            else:  # 若设备名在
                deviceName = params['deviceName']
                params.pop('deviceName')
                # queryset = models.epRunning.objects.filter(eid__deviceName=deviceName).filter(**params)
                # # queryset = models.epRunning.objects.filter(eid__category="生物质发电")
                # serializer = epRunningSerializer(instance=queryset, many=True)
                if 'enableDate' not in params.keys():
                    queryset = epRunning.objects.filter(eid__deviceName=deviceName).filter(**params)
                    serializer = epRunningSerializer(instance=queryset, many=True)
                    return Response(serializer.data, status=status.HTTP_200_OK)
                else:
                    enableDate = params['enableDate']
                    params.pop('enableDate')
                    queryset = epRunning.objects.filter(eid__deviceName=deviceName).filter(enableDate__contains=
                                                                                           enableDate).filter(**params)
                    serializer = epRunningSerializer(instance=queryset, many=True)
                    return Response(serializer.data, status=status.HTTP_200_OK)


        else:
            return self.list(request)

    def post(self, request):
        """
        管理员批量添加运行设备的数据
        :param request:
        :return:
        """
        self.permission_classes = [isAdmin]  # 管理员可访问
        self.check_permissions(request)
        datas = request.data
        for data in datas:
            epRunning(eid_id=data['eid'], place=data['place'], belongIn=data['belongIn'], isActive=data['isActive'],
                      inUsing=data['inUsing'], enableDate=data['enableDate']).save()
            # epRunning.objects.create(**data)  # 报错要求提供一个外键的实体
            epobj = models.equipment.objects.filter(id=data['eid'])
            orgexist = epobj[0].exist
            # print(orgexist-1)
            models.equipment.objects.filter(id=data['eid']).update(exist=orgexist - 1)  # 更新库存备件数

        return Response(datas, status=status.HTTP_201_CREATED)

    def patch(self, request, pk):
        """
        局部更新
        用于修正错误数据
        :param request:
        :param pk:
        :return:
        """
        return self.partial_update(request)

    def delete(self, request, pk):
        self.permission_classes = [isAdmin]  # 管理员可访问
        self.check_permissions(request)
        """
        删除错误数据
        :param request:
        :param pk:
        :return:
        """
        return self.destroy(request)


@method_decorator(csrf_exempt, name='dispatch')
class repairGenView(GenericAPIView, ListModelMixin, RetrieveModelMixin, CreateModelMixin, UpdateModelMixin,
                    DestroyModelMixin):
    serializer_class = repairSerializer
    queryset = repair.objects.all()

    #authentication_classes = []  # 不认证
    permission_classes = []  # 不鉴权

    def get(self, request):
        self.permission_classes = [isAdmin | isWorker]
        self.check_permissions(request)
        params = dict(request.query_params)
        if bool(params):
            for key, val in params.items():
                params[key] = val[0]
            """如果传递的有参数"""
            if 'category' in params.keys():
                category = params['category']
                params.pop('category')
                if 'repairDate' in params.keys():
                    repairDate = params['repairDate']
                    params.pop('repairDate')

                    queryset = models.repair.objects.filter(eprid__eid__category=category).filter(repairDate__contains=
                                                                                                  repairDate).filter(
                        **params)
                else:
                    queryset = models.repair.objects.filter(eprid__eid__category=category).filter(
                        **params)
                serializer = repairSerializer(instance=queryset, many=True)
                return Response(serializer.data, status.HTTP_200_OK)
            else:
                if 'repairDate' in params.keys():
                    repairDate = params['repairDate']
                    params.pop('repairDate')

                    queryset = models.repair.objects.filter(repairDate__contains=repairDate).filter(**params)
                else:
                    queryset = models.repair.objects.filter(**params)
                serializer = repairSerializer(instance=queryset, many=True)
                return Response(serializer.data, status.HTTP_200_OK)
        else:
            return self.list(request)

    def post(self, request):
        # 需要指定经办人
        workers = user.objects.filter(type=3).values_list("id").order_by('?').first()  # 随机指定经办人

        # workers=dict(workers)
        # print(workers)
        data = request.data
        data['uid'] = workers[0]

        # 将该运行设备的状态置为False
        epRunning.objects.filter(id=data['eprid']).update(isActive=0, inUsing=0)  # 数据库里这两个字段的属性是tinyint

        serializer = repairSerializer1(data=data)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(serializer.data, status.HTTP_201_CREATED)

    def patch(self, request, pk):
        self.permission_classes = [isAdmin | isWorker]
        self.check_permissions(request)
        return self.partial_update(request)


@method_decorator(csrf_exempt, name='dispatch')
class scrapGenView(GenericAPIView, ListModelMixin, CreateModelMixin):
    serializer_class = scrapSerializer
    queryset = scrap.objects.all()

    #authentication_classes = []  # 不认证
    permission_classes = []  # 不鉴权

    def get(self, request):
        self.permission_classes = [isAdmin]
        self.check_permissions(request)
        params = dict(request.query_params)
        if bool(params):
            for key, val in params.items():
                params[key] = val[0]
            """如果传递的有参数"""
            if 'category' in params.keys():
                category = params['category']
                params.pop('category')
                if 'scrapDate' in params.keys():
                    queryset = models.scrap.objects.filter(eid__category=category).filter(scrapDate__contains=
                                                                                  params['scrapDate'])
                else:
                    queryset = models.scrap.objects.filter(eid__category=category)
                # queryset = models.epRunning.objects.filter(eid__category="生物质发电")
                serializer = scrapSerializer(instance=queryset, many=True)
                return Response(serializer.data, status.HTTP_200_OK)
            elif 'scrapDate' in params.keys():
                queryset = models.scrap.objects.filter(scrapDate__contains=params['scrapDate'])
                serializer = scrapSerializer(instance=queryset, many=True)
                return Response(serializer.data, status.HTTP_200_OK)
            else:
                return self.list(request)
        else:
            return self.list(request)

    def post(self, request):
        self.permission_classes = [isAdmin | isWorker]
        self.check_permissions(request)
        datas = request.data
        serializer = scrapSerializer1(data=datas, many=True)
        serializer.is_valid(raise_exception=True)
        serializer.save()
        return Response(datas, status.HTTP_201_CREATED)


class components(GenericAPIView):
    # authentication_classes = []  # 不认证
    permission_classes = []  # 不鉴权

    def get(self, request):
        deviceName = models.equipment.objects.values_list('deviceName').distinct()
        category = models.equipment.objects.values_list('category').distinct()
        equipment = {'deviceName': deviceName, 'category': category}

        belongIn = models.epRunning.objects.values_list('belongIn').distinct()
        deviceName = models.epRunning.objects.values_list('eid__deviceName').distinct()
        category = models.epRunning.objects.values_list('eid__category').distinct()
        ep = {'belongIn': belongIn, 'deviceName': deviceName, 'category': category}

        category = models.repair.objects.values_list('eprid__eid__category').distinct()
        repairFactory = models.repair.objects.values_list('repairFactory').distinct()
        deviceName = models.repair.objects.values_list('eprid__eid__deviceName').distinct()
        re = {'category': category, 'deviceName': deviceName, 'repairFactory': repairFactory}

        category = models.scrap.objects.values_list('eid__category').distinct()
        deviceName = models.scrap.objects.values_list('eid__deviceName').distinct()
        sc = {'category': category, 'deviceName': deviceName}
        return Response({"equipment": equipment, "epRunning": ep, "repair": re, "scrap": sc}, status=status.HTTP_200_OK)



@method_decorator(csrf_exempt, name='dispatch')
class fileUploadGenView(GenericAPIView, ListModelMixin, RetrieveModelMixin, CreateModelMixin, UpdateModelMixin,
                DestroyModelMixin):
    #authentication_classes = []  # 不认证
    permission_classes = []  # 不鉴权

    # lookup_field = 'pk'
    queryset = uploadFile.objects.all()
    serializer_class = uploadFileSerializer

    def post(self, request):
        """
        任意用户上传头像
        :param request:
        :return:
        """
        
        file = request.FILES.getlist("uploadfile")
        # print(file[0].name) # 输出文件名
        serializer = self.get_serializer(data={"file": file[0]})
        serializer.is_valid(raise_exception=True)
        serializer.save()

        token = request.META.get('HTTP_AUTHORIZATION')
        salt = settings.SECRET_KEY
        payload = jwt.decode(token, salt, True)
        models.user.objects.filter(id=payload['id']).update(pid=serializer.data["id"])

        return Response(serializer.data, status=status.HTTP_201_CREATED)


@method_decorator(csrf_exempt, name='dispatch')
class userDetailGenView(GenericAPIView, ListModelMixin, CreateModelMixin, RetrieveModelMixin, DestroyModelMixin,
                 UpdateModelMixin):
    
    authentication_classes = []
    permission_classes=[]

   # authentication_classes = []  # 不认证
   # permission_classes = []  # 不鉴权

    serializer_class = out_userSerializer
    queryset = user.objects.all()

    def get(self, request):
        """
        管理员查看（指定类型）用户
        :param request:
        :return: 不返回密码
        """
        token = request.META.get('HTTP_AUTHORIZATION')
        salt = settings.SECRET_KEY
        payload = jwt.decode(token, salt, True)
        queryset = user.objects.get(id=payload['id'])
        serializer = out_userSerializer(instance=queryset)
        return Response(serializer.data, status=status.HTTP_200_OK)


@method_decorator(csrf_exempt, name='dispatch')
class downloadGenView(GenericAPIView, ListModelMixin, CreateModelMixin, RetrieveModelMixin, DestroyModelMixin,
                 UpdateModelMixin):
    

    permission_classes=[isAdmin]

    #authentication_classes = []  # 不认证
    #permission_classes = []  # 不鉴权

    # serializer_class = out_userSerializer
    queryset = user.objects.all()

    def get(self, request):
        """
        管理员查看（指定类型）用户
        :param request:
        :return: 不返回密码
        """
        # filepath = "/code/dockerfile"
        import os
        import re
        filepath = os.path.join(os.getcwd(),"testDownload.txt")
        #print(filepath)
        params = dict(request.query_params)
        #if "filepath" in params.keys():
        #    filepath = params["filepath"][0]
        
        file=open(filepath,'rb')

        response =FileResponse(file)
        response['Content-Type']='application/octet-stream'
        response['Content-Disposition']='attachment;filename="{0}"'.format(re.split(r'[/\\]',filepath)[-1])
        return response
        

        # data = {}
        # data["当前目录"] = os.getcwd()
        # data["上级目录"] = os.path.abspath('..')
        # data["再上级目录"] = os.path.abspath('../..')
        # data["当前目录列表"] = os.listdir(os.getcwd())
        # data["etc目录列表"] = os.listdir('/etc/')